﻿using Blm.PgsqlDriver.Helpers;
using Blm.Utils.Extensions;
using Blm.VisionCloud.FrameWork.Cached;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using VisionCloud.Core.Model.Enums;
using VisionCloud.Core.Model.Ms;
using VisionCloud.Core.Model.Sys;
using VisionCloud.Domain.Common;
using VisionCloud.Domain.Data;
using VisionCloud.Domain.DtoModel.MiniApp;
using VisionCloud.Domain.DtoModel.Ms;
using VisionCloud.Domain.Extension;
using VisionCloud.Domain.Repository.Interface.Ms;
using VisionCloud.Domain.Repository.Interface.Sys;
using VisionCloud.Utility;
using static VisionCloud.Domain.Data.DataStore;

namespace VisionCloud.Domain.Repository.Implement.Ms
{
    public class MsTaskRepository : BaseRepository<MsTask>, IMsTaskRepository
    {
        public ISysUserProjectRepository SysUserProjectRepository { get; set; }

        private OperatorInfo tokenModel => OperatorProvider.Get();

        private readonly ICached cached;

        public MsTaskRepository(ICached cached)
        {
            this.cached = cached;
        }

        public async ValueTask<List<TaskInfoResponseDto>> GetTaskListAsync(QueryTaskRequestDto dto, Guid userId, Guid? projectStandardId)
        {
            var propertyArr = new string[] { TaskPropertyEnum.初测.ToString(), TaskPropertyEnum.复测.ToString() };
            var index = Math.Max((dto.PageIndex - 1), 0) * dto.PageSize;
            var list = await (from t in Db.MsTasks
                              join p in Db.MsProjectStandards on new { t.ProjectStandardId, t.ProjectId } equals new { p.ProjectStandardId, ProjectId = p.ProjectGuid }
                              where t.CreatedBy == userId && t.IsDeleted == false
                                    && (projectStandardId == null || t.ProjectStandardId == projectStandardId)
                                    && (dto.TaskType == null || t.TaskType == dto.TaskType)
                                    && t.MeasureAPP == MeasureAPPEnum.小程序
                                    && (dto.TaskProperty == null
                                        || (dto.TaskProperty != TaskPropertyEnum.其他 && dto.TaskProperty.ToString() == t.TaskProperty)
                                        || (dto.TaskProperty == TaskPropertyEnum.其他 && !propertyArr.Contains(t.TaskProperty))
                                        )
                              select new TaskInfoResponseDto
                              {
                                  TaskId = t.TaskId,
                                  TaskName = t.TaskName,
                                  ProjectId = t.ProjectId,
                                  ProjectStandardId = t.ProjectStandardId,
                                  TaskProperty = t.TaskProperty,
                                  Status = t.Status,
                                  TaskType = t.TaskType.ToString(),
                                  ProjectStage = p.Stage,
                                  CreateTime = t.CreatedDate
                              }).OrderByDescending(t => t.CreateTime).Skip(index).Take(dto.PageSize).ToListAsync();

            return list;
        }

        public async Task<ApiPageResult> GetPage(TaskCm condition)
        {
            // var standards = DataStore.GetStandards(condition.ProjectId);
            var userProjects = await GetUserProjects(tokenModel.Id);

            var list = await (from t in Db.MsTasks
                              join p in Db.MsProjects on t.ProjectId equals p.ProjectId
                              join u in Db.SysUsers on t.CreatedBy equals u.YunUserGuid
                              join u2 in Db.SysUsers on t.UserId equals u2.YunUserGuid
                              join std in Db.MsProjectStandards on new { projectGuid = t.ProjectId, t.ProjectStandardId }
                              equals new { projectGuid = std.ProjectGuid, std.ProjectStandardId }
                              where (string.IsNullOrWhiteSpace(condition.ProjectName) || p.Name.Contains(condition.ProjectName))
                                    && (string.IsNullOrWhiteSpace(condition.BuildingFloor) || t.BuildingFloor.Contains(condition.BuildingFloor))
                                    && (string.IsNullOrWhiteSpace(condition.BuildingBlock) || t.BuildingBlock.Contains(condition.BuildingBlock))
                                    && (string.IsNullOrWhiteSpace(condition.TaskName) || t.TaskName.Contains(condition.TaskName))
                                    && (string.IsNullOrWhiteSpace(condition.CreateUser) || u.Name.Contains(condition.CreateUser))
                                    && (condition.HouseMapId == Guid.Empty || t.HouseMapId == condition.HouseMapId)
                                    && (condition.TaskId == Guid.Empty || t.TaskId == condition.TaskId)
                                    && (condition.ProjectId == Guid.Empty || t.ProjectId == condition.ProjectId)
                                    && (condition.StartDate == null || t.CreatedDate >= condition.StartDate)
                                    && (condition.EndDate == null || t.CreatedDate <= condition.EndDate.Value.AddDays(1))
                                    && (condition.UserId == Guid.Empty || t.UserId == condition.UserId)
                                    && (condition.TaskType == null || t.TaskType == condition.TaskType.Value)
                                 && userProjects.Contains(t.ProjectId)

                                    && !p.IsDeleted && p.Status == MsProject.ProjectStatus.启用
                                    && !t.IsDeleted
                                    && (condition.Status == null || (condition.Status == MsTask.TaskStatus.已完成
                                            ? t.Status == MsTask.TaskStatus.已完成
                                            : t.Status != MsTask.TaskStatus.已完成))
                              select new TaskLm()
                              {
                                  ProjectId = t.ProjectId,
                                  BuildingBlock = t.BuildingBlock,
                                  BuildingFloor = t.BuildingFloor,
                                  HouseMapId = t.HouseMapId,
                                  TaskId = t.TaskId,
                                  ProjectName = p.Name,
                                  OperatorName = u2.Name,
                                  CreateUserName = u.Name,
                                  CreateDate = t.CreatedDate,
                                  LastUpdatedDate = t.LastUpdatedDate,
                                  StatusStr = t.Status.ToString(),
                                  Status = t.Status,
                                  HouseMapPoints = t.HouseMapPoints,
                                  Craft = t.Craft,
                                  ProjectStandardId = t.ProjectStandardId,
                                  UserId = t.UserId,
                                  TaskType = t.TaskType,
                                  ProjectStage = std.Stage,
                                  IsNew = t.IsNew,
                                  UseStandards = t.UseStandards,
                                  HouseHolds = t.HouseHolds,
                                  SupportStandard = t.SupportStandard,
                                  TaskName = t.TaskName,
                                  TaskNameNo = t.TaskNameNo,
                                  UsestandardAllInfo = t.UsestandardAllInfo,
                                  TaskProperty = t.TaskProperty,
                                  HouseType = t.HouseType,
                                  AlgorithmParamTemplateGuid = t.AlgorithmParamTemplateGuid,
                                  AlgorithmParamTemplateName = t.AlgorithmParamTemplateName,
                                  IsMobileInputManualMeasurement = t.IsMobileInputManualMeasurement,
                                  ManualMeasurementStatus = (int)t.ManualMeasurementStatus,
                                  MobileInputUserName = t.MobileInputUserName,
                                  MobileInputUserGuid = t.MobileInputUserGuid,
                              }).AsNoTracking()
                .OrderByDescending(w => w.IsNew)
                .ThenByDescending(w => w.CreateDate)
                .ToPageList(condition).ConfigureAwait(false);

            var result = condition.CopyTo<ApiPageResult>();
            result.PageData = list;
            return result;
        }

        public async Task<TaskSfm> GetModel(Guid taskId, string houseTypeName = null)
        {
            var projectGuid = (from t in Db.MsTasks where t.TaskId == taskId select t.ProjectId).FirstOrDefault();
            var standards = DataStore.GetStandards(projectGuid);

            var result = await (
                from t in Db.MsTasks
                join p in Db.MsProjects on t.ProjectId equals p.ProjectId
                join c in Db.SysUsers on t.CreatedBy equals c.YunUserGuid
                join u in Db.SysUsers on t.UserId equals u.YunUserGuid
                where t.TaskId == taskId && !t.IsDeleted

                select new TaskSfm(t)
                {
                    TaskName = t.TaskName,
                    TaskNameNo = t.TaskNameNo,
                    HouseHolds = t.HouseHolds,
                    Details = p.Details.ToObject<List<Detail>>(),
                    ProjectStandardId = t.ProjectStandardId,
                    StatusStr = t.Status.ToString(),
                    ProjectName = p.Name,
                    CreatedByName = c.Name,
                    UserName = u.Name,
                    AllStandardInfo = t.UsestandardAllInfo,
                    UseStandards = string.IsNullOrWhiteSpace(t.UseStandards) ? new UseStandard() : t.UseStandards.ToObject<UseStandard>(),
                    UnqualifiedIndexList = t.UnqualifiedIndexList,
                    DotCloudDeleted = t.DotCloudDeleted,
                    HouseType = t.HouseType,
                    MeasureType = Enum.Parse<MeasureTypeEnum>(t.MeasureType)
                }
            ).AsNoTracking().SingleOrDefaultAsync().ConfigureAwait(false);

            result.ProjectStage = standards.FirstOrDefault(w => w.ProjectStandardId == result.ProjectStandardId)?.Stage;

            if (result != null)
            {
                var rppath = (from t in Db.MsTaskReport where t.TaskId == result.TaskId select t).FirstOrDefault();
                if (rppath != null)
                {
                    result.ReportPath = rppath.ReportPath;
                }

                #region 测量点信息

                var points = await Db.MsTasks
                          .Join(Db.TaskPointss,
                                x => x.TaskId,
                                y => y.TaskId,
                                (x, y) => new { Task = x, TaskPoint = y })
                          .Join(Db.MsPointTypes,
                                x => new { ProjectId = x.Task.ProjectId, MsPointTypeId = x.TaskPoint.MsPointTypeId },
                                y => new { ProjectId = y.ProjectGuid, MsPointTypeId = y.Id },
                                (x, y) => new
                                {
                                    IsDeleted = x.TaskPoint.IsDeleted,
                                    TaskId = x.Task.TaskId,
                                    filePath = x.TaskPoint.filePath,
                                    pintIndex = x.TaskPoint.pintIndex,
                                    status = x.TaskPoint.status,
                                    xPoint = x.TaskPoint.x,
                                    yPoint = x.TaskPoint.y,
                                    pointId = x.TaskPoint.pointId,
                                    rate = x.TaskPoint.rate,
                                    IsManualMeasureInput = x.TaskPoint.IsManualMeasureInput,
                                    UseStandards = x.TaskPoint.UseStandards,
                                    HouseTypeName = x.TaskPoint.HouseTypeName,
                                    SubPointList = x.TaskPoint.SubPointList,
                                    Type = y.Type,
                                    MsPointTypeName = y.Name
                                })
                          .GroupJoin(Db.MsManualMeasureReports,
                                x => new { TaskId = x.TaskId, PointIndex = x.pintIndex },
                                y => new { TaskId = y.TaskId, PointIndex = y.PointIndex },
                                (x, y) => new
                                {
                                    IsDeleted = x.IsDeleted,
                                    TaskId = x.TaskId,
                                    filePath = x.filePath,
                                    pintIndex = x.pintIndex,
                                    status = x.status,
                                    xPoint = x.xPoint,
                                    yPoint = x.yPoint,
                                    pointId = x.pointId,
                                    rate = x.rate,
                                    IsManualMeasureInput = x.IsManualMeasureInput,
                                    UseStandards = x.UseStandards,
                                    HouseTypeName = x.HouseTypeName,
                                    SubPointList = x.SubPointList,
                                    Type = x.Type,
                                    MsPointTypeName = x.MsPointTypeName,
                                    Report = y,
                                })
                          .SelectMany(x => x.Report.DefaultIfEmpty(),
                                (x, y) => new
                                {
                                    IsDeleted = x.IsDeleted,
                                    TaskId = x.TaskId,
                                    filePath = x.filePath,
                                    pintIndex = x.pintIndex,
                                    status = x.status,
                                    xPoint = x.xPoint,
                                    yPoint = x.yPoint,
                                    pointId = x.pointId,
                                    rate = x.rate,
                                    IsManualMeasureInput = x.IsManualMeasureInput,
                                    UseStandards = x.UseStandards,
                                    HouseTypeName = x.HouseTypeName,
                                    SubPointList = x.SubPointList,
                                    Type = x.Type,
                                    MsPointTypeName = x.MsPointTypeName,
                                    ManualReportStatus = y.ReportStatus,
                                    ManualReportErrMsg = y.ReportErrMsg,
                                })
                          .Where(x => x.TaskId == taskId && !x.IsDeleted)
                          .WhereIf(!string.IsNullOrEmpty(houseTypeName), x => x.HouseTypeName == houseTypeName)
                          .Select(x => new TaskPointDto
                          {
                              taskId = x.TaskId,
                              filePath = x.filePath,
                              pointIndex = x.pintIndex,
                              status = x.status,
                              x = x.xPoint,
                              y = x.yPoint,
                              pointId = x.pointId,
                              rateValue = x.rate,
                              Type = x.Type,
                              MsPointTypeName = x.MsPointTypeName,
                              IsManualMeasureInput = x.IsManualMeasureInput,
                              UseStandards = !string.IsNullOrWhiteSpace(x.UseStandards) ? x.UseStandards.ToObject<UseStandard>() : new UseStandard(),
                              ManualReportStatusStr = x.ManualReportStatus.ToString(),
                              ManualReportErrMsg = x.ManualReportErrMsg,
                              HouseTypeName = x.HouseTypeName,
                              SubPointList = x.SubPointList
                          })
                          .OrderBy(x => x.pointIndex).AsNoTracking().ToListAsync().ConfigureAwait(false);

                result.Points = points;

                #endregion 测量点信息

                #region 站点测量项

                // 记录所有站点测量项（测量项并集）
                List<string> robotMeasureItems = new List<string>();
                if (result.Points != null)
                {
                    var taskMeasureItems = await Db.MSTaskPoint2ManualMeasurements.Join(Db.MsTaskMeasureItemTemplates,
                                                                                    x => x.MsTaskMeasureItemTemplateId, y => y.MsTaskMeasureItemTemplateId,
                                                                                    (x, y) => new { Measurements = x, Templates = y })
                                                                            .Where(x => x.Measurements.TaskId == taskId)
                                                                            .Select(x => new MeasureItem
                                                                            {
                                                                                MSTaskPoint2ManualMeasurementId = x.Measurements.MSTaskPoint2ManualMeasurementId,
                                                                                Title = x.Measurements.Title,
                                                                                Id = x.Measurements.ManualMeasurementTypeId,
                                                                                Code = x.Measurements.Code,
                                                                                Unit = x.Measurements.Unit,
                                                                                Type = x.Templates.Type,
                                                                                PointId = x.Measurements.PointId.ToString(),
                                                                                Desc = String.Empty,
                                                                                DisplayValue = $"{x.Measurements.ManualMeasurementTypeId}",
                                                                                DesignValues = (x.Measurements.DesignValues ?? x.Templates.DesignValues).ToObject<List<DesignValue>>()
                                                                            }).OrderBy(x => x.Code).AsNoTracking().ToListAsync().ConfigureAwait(false);

                    foreach (var point in result.Points)
                    {
                        point.MeasureItems = taskMeasureItems.Where(p => p.PointId == point.pointId.ToString()).ToList();
                        if (point.MeasureItems != null)
                        {
                            foreach (var mi in point.MeasureItems)
                            {
                                // 构造设计值
                                string value = string.Empty;
                                if (mi.DesignValues != null)
                                {
                                    foreach (var des in mi?.DesignValues)
                                    {
                                        value += $"{des.Title}:{(int)des.Value},";
                                    }
                                    if (!string.IsNullOrWhiteSpace(value))
                                    {
                                        mi.DisplayValue = mi.Id + ":" + value.Substring(0, value.Length - 1);
                                    }
                                }

                                // 构造实测值
                                value = string.Empty;
                                if (mi.MeasuredValues != null)
                                {
                                    foreach (var des in mi.MeasuredValues)
                                    {
                                        value += $"{des.Title}:{des.Value},";
                                    }
                                    if (!string.IsNullOrWhiteSpace(value))
                                    {
                                        mi.MeasuredDisplayValue = mi.Id + ":" + value.Substring(0, value.Length - 1);
                                    }
                                }

                                if (string.Equals(mi.Code, "r-hunningtuqiangdu", StringComparison.OrdinalIgnoreCase))
                                {
                                    if (mi.DesignValues != null && mi.DesignValues.Count > 0)
                                    {
                                        var newItem = new MeasuredValue()
                                        {
                                            Title = mi.DesignValues[0].Title,
                                            Key = mi.DesignValues[0].Key,
                                            Value = mi.DesignValues[0].Value,
                                            Unit = mi.DesignValues[0].Unit,
                                        };
                                        mi.MeasuredValues.Add(newItem);
                                        mi.MeasuredValues.Reverse();           // 把设计值放到原始开头
                                        mi.DesignValues = new List<DesignValue>();
                                    }
                                }
                            }
                        }
                        if (point.UseStandards.robot != null && point.UseStandards.robot.Count > 0)
                        {
                            foreach (var mi in point.UseStandards.robot)
                            {
                                if (!robotMeasureItems.Contains(mi))
                                {
                                    robotMeasureItems.Add(mi);
                                }
                            }
                        }
                    }
                }

                #endregion 站点测量项

                #region 标准库信息处理

                if (!string.IsNullOrEmpty(result.UsestandardAllInfo) && result.MeasureType != MeasureTypeEnum.外立面任务)
                {
                    StandardClass standardModelSig = result.UsestandardAllInfo.ToObject<StandardClass>();
                    List<StandardClass> standardModel = new List<StandardClass>();
                    standardModel.Add(standardModelSig);

                    result.UseStandards.robot = robotMeasureItems;
                    foreach (var classItem in standardModel)
                    {
                        var selectClass = new StandardClass
                        {
                            Code = classItem.Code,
                            ClassName = "机器测量标准",//classItem.ClassName,
                            Items = (from u in
                                         (from w in result.UseStandards.robot select w)
                                     join i in classItem.Items
                                        on u equals i.Code
                                     where
                                        (string.IsNullOrEmpty(i.SupportCraft) || i.SupportCraft == result.Craft)
                                     && (string.IsNullOrEmpty(i.SupportStandard) || i.SupportStandard == result.SupportStandard)
                                     select i).ToList()
                        };
                        result.UseStandardsStr.Add(selectClass);
                        if (result.UseStandards.man.Count != 0)
                        {
                            var manClass = new StandardClass
                            {
                                Code = "man",
                                ClassName = "人工测量标准",
                                Items = (from u in
                                             (from v in result.UseStandards.man select v)
                                         join i in classItem.Items
                                            on u equals i.Code
                                         where
                                            (string.IsNullOrEmpty(i.SupportCraft) || i.SupportCraft == result.Craft)
                                         && (string.IsNullOrEmpty(i.SupportStandard) || i.SupportStandard == result.SupportStandard)
                                         select i).ToList()
                            };
                            result.UseStandardsStr.Add(manClass);
                        }
                    }
                }

                #endregion 标准库信息处理
            }
            return result;
        }

        public async Task<TaskSfm> GetModel(MsTask model)
        {
            var taskId = model.TaskId;
            var projectGuid = model.ProjectId;
            var standards = DataStore.GetStandards(projectGuid);

            var result = await (
                from t in Db.MsTasks
                join p in Db.MsProjects on t.ProjectId equals p.ProjectId
                join c in Db.SysUsers on t.CreatedBy equals c.YunUserGuid
                join u in Db.SysUsers on t.UserId equals u.YunUserGuid
                where t.TaskId == taskId && !t.IsDeleted

                select new TaskSfm(t)
                {
                    TaskName = t.TaskName,
                    TaskNameNo = t.TaskNameNo,
                    HouseHolds = t.HouseHolds,
                    DetailsStr = p.Details,
                    ProjectStandardId = t.ProjectStandardId,
                    StatusStr = t.Status.ToString(),
                    ProjectName = p.Name,
                    CreatedByName = c.Name,
                    UserName = u.Name,
                    AllStandardInfo = t.UsestandardAllInfo,
                    UseStandards = string.IsNullOrWhiteSpace(t.UseStandards) ? new UseStandard() : t.UseStandards.ToObject<UseStandard>(),
                    UnqualifiedIndexList = t.UnqualifiedIndexList,
                    DotCloudDeleted = t.DotCloudDeleted,
                    HouseType = t.HouseType,
                    AlgorithmParamTemplateName = t.AlgorithmParamTemplateName,
                    RobotCategoryStr = t.RobotCategory,
                    InnerWallVersion = t.InnerWallRobotVersion
                }
            ).AsNoTracking().SingleOrDefaultAsync();

            if (result != null)
            {
                result.Details = GetDetails(result.DetailsStr);
                result.ProjectStage = standards.Single(w => w.ProjectStandardId == result.ProjectStandardId).Stage;
                result.RobotCategory = GetRobotCategory(result.RobotCategoryStr);
                result.ReportPath = (await Db.MsTaskReport.FirstOrDefaultAsync(t => t.TaskId == result.TaskId))?.ReportPath;

                #region 测量点信息

                var points = await
                    (
                      from p in Db.TaskPointss
                      join a in Db.MsPointTypes on p.MsPointTypeId equals a.Id
                      where p.TaskId == taskId && !p.IsDeleted && a.ProjectGuid == projectGuid
                      select new TaskPointDto()
                      {
                          taskId = taskId,
                          filePath = p.filePath,
                          pointIndex = p.pintIndex,
                          status = p.status,
                          x = p.x,
                          y = p.y,
                          pointId = p.pointId,
                          rateValue = p.rate,
                          Type = a.Type,
                          MsPointTypeName = a.Name,
                          IsManualMeasureInput = p.IsManualMeasureInput,
                          UseStandards = !string.IsNullOrWhiteSpace(p.UseStandards) ? p.UseStandards.ToObject<UseStandard>() : new UseStandard(),
                          HouseTypeName = p.HouseTypeName,
                          HouseTypeKey = p.HouseTypeKey,
                          SubPointList = p.SubPointList,
                      }
                    ).OrderBy(i => i.pointIndex).AsNoTracking().ToListAsync();
                var manualReports = await Db.MsManualMeasureReports.Where(x => x.TaskId == taskId).Select(y => new { y.ReportStatus, y.ReportErrMsg, y.PointIndex }).ToListAsync();
                if (manualReports.IsNotEmpty())
                {
                    foreach (var p in points)
                    {
                        var report = manualReports.FirstOrDefault(x => x.PointIndex == p.pointIndex);
                        p.ManualReportStatusStr = report?.ReportStatus.ToString();
                        p.ManualReportErrMsg = report?.ReportErrMsg;
                    }
                }
                result.Points = points;

                #endregion 测量点信息

                #region 站点测量项

                // 记录所有站点测量项（测量项并集）
                List<string> robotMeasureItems = new List<string>();
                if (result.Points.IsNotEmpty())
                {
                    var taskMeasureItems = await (
                                   from a in Db.MSTaskPoint2ManualMeasurements
                                   join b in Db.MsTaskMeasureItemTemplates on a.MsTaskMeasureItemTemplateId equals b.MsTaskMeasureItemTemplateId into t
                                   from tt in t.DefaultIfEmpty()
                                   where a.TaskId == taskId
                                   select new MeasureItem()
                                   {
                                       MSTaskPoint2ManualMeasurementId = a.MSTaskPoint2ManualMeasurementId,
                                       Title = a.Title,
                                       Id = a.ManualMeasurementTypeId,
                                       Code = a.Code,
                                       Unit = a.Unit,
                                       Type = tt.Type,
                                       PointId = a.PointId.ToString(),
                                       Desc = string.Empty,
                                       DisplayValue = !string.IsNullOrWhiteSpace(tt.Id) ? $"{tt.Id}:" : !string.IsNullOrWhiteSpace(a.ManualMeasurementTypeId) ? $"{a.ManualMeasurementTypeId}" : "",
                                       DesignValues = !string.IsNullOrWhiteSpace(tt.DesignValues) ? tt.DesignValues.ToObject<List<DesignValue>>() :
                                       (a.DesignValues != null ? a.DesignValues.ToObject<List<DesignValue>>() : new List<DesignValue>()),
                                       MeasuredValues = !string.IsNullOrWhiteSpace(a.Values) ? a.Values.ToObject<List<MeasuredValue>>() : new List<MeasuredValue>()           // 实际测量值
                                   }).OrderBy(x => x.Code).AsNoTracking().ToListAsync();

                    foreach (var point in result.Points)
                    {
                        point.MeasureItems = taskMeasureItems.Where(p => p.PointId == point.pointId.ToString()).ToList();
                        if (point.MeasureItems != null)
                        {
                            foreach (var mi in point.MeasureItems)
                            {
                                // 构造设计值
                                string value = string.Empty;
                                if (mi.DesignValues != null)
                                {
                                    foreach (var des in mi?.DesignValues)
                                    {
                                        value += $"{des.Title}:{(int)des.Value},";
                                    }
                                    if (!string.IsNullOrWhiteSpace(value))
                                    {
                                        mi.DisplayValue = mi.Id + ":" + value.Substring(0, value.Length - 1);
                                    }
                                }

                                // 构造实测值
                                value = string.Empty;
                                if (mi.MeasuredValues != null)
                                {
                                    foreach (var des in mi.MeasuredValues)
                                    {
                                        value += $"{des.Title}:{des.Value},";
                                    }
                                    if (!string.IsNullOrWhiteSpace(value))
                                    {
                                        mi.MeasuredDisplayValue = mi.Id + ":" + value.Substring(0, value.Length - 1);
                                    }
                                }

                                if (string.Equals(mi.Code, "r-hunningtuqiangdu", StringComparison.OrdinalIgnoreCase))
                                {
                                    if (mi.DesignValues != null && mi.DesignValues.Count > 0)
                                    {
                                        var newItem = new MeasuredValue()
                                        {
                                            Title = mi.DesignValues[0].Title,
                                            Key = mi.DesignValues[0].Key,
                                            Value = mi.DesignValues[0].Value,
                                            Unit = mi.DesignValues[0].Unit,
                                        };
                                        mi.MeasuredValues.Add(newItem);
                                        mi.MeasuredValues.Reverse();           // 把设计值放到原始开头
                                        mi.DesignValues = new List<DesignValue>();
                                    }
                                }
                            }
                        }
                        if (point.UseStandards.robot != null && point.UseStandards.robot.Count > 0)
                        {
                            foreach (var mi in point.UseStandards.robot)
                            {
                                if (!robotMeasureItems.Contains(mi))
                                {
                                    robotMeasureItems.Add(mi);
                                }
                            }
                        }
                    }
                }

                #endregion 站点测量项

                #region 标准库信息处理

                if (!string.IsNullOrEmpty(result.UsestandardAllInfo))
                {
                    StandardClass standardModelSig = result.UsestandardAllInfo.ToObject<StandardClass>();
                    List<StandardClass> standardModel = new List<StandardClass>
                    {
                        standardModelSig
                    };

                    result.UseStandards.robot = robotMeasureItems;
                    foreach (var classItem in standardModel)
                    {
                        var selectClass = new StandardClass
                        {
                            Code = classItem.Code,
                            ClassName = "机器测量标准",//classItem.ClassName,
                            Items = (from u in
                                         (from w in result.UseStandards.robot select w)
                                     join i in classItem.Items
                                        on u equals i.Code
                                     where
                                        (string.IsNullOrEmpty(i.SupportCraft) || i.SupportCraft == result.Craft)
                                     && (string.IsNullOrEmpty(i.SupportStandard) || i.SupportStandard == result.SupportStandard)
                                     select i).ToList()
                        };
                        result.UseStandardsStr.Add(selectClass);
                        if (result.UseStandards.man.Count != 0)
                        {
                            var manClass = new StandardClass
                            {
                                Code = "man",
                                ClassName = "人工测量标准",
                                Items = (from u in
                                             (from v in result.UseStandards.man select v)
                                         join i in classItem.Items
                                            on u equals i.Code
                                         where
                                            (string.IsNullOrEmpty(i.SupportCraft) || i.SupportCraft == result.Craft)
                                         && (string.IsNullOrEmpty(i.SupportStandard) || i.SupportStandard == result.SupportStandard)
                                         select i).ToList()
                            };
                            result.UseStandardsStr.Add(manClass);
                        }
                    }
                }

                #endregion 标准库信息处理
            }

            return result;
        }

        private List<Detail> GetDetails(string details)
        {
            try
            {
                return details.ToObject<List<Detail>>();
            }
            catch
            {
                return new List<Detail>();
            }
        }

        private List<RobotCategoryEnum> GetRobotCategory(string RobotCategoryStr)
        {
            var res = new List<RobotCategoryEnum>();
            if (string.IsNullOrEmpty(RobotCategoryStr)) return res;
            var arr = RobotCategoryStr?.Split('|');
            foreach (var ca in arr)
            {
                switch (ca)
                {
                    case "天花":
                        res.Add(RobotCategoryEnum.天花);
                        break;

                    case "螺杆洞":
                        res.Add(RobotCategoryEnum.螺杆洞);
                        break;

                    case "内墙":
                        res.Add(RobotCategoryEnum.内墙);
                        break;
                }
            }
            return res;
        }

        public async Task<List<ProjectRobot>> GetProjectRobot(Guid projectId)
        {
            return await Db.MsProjectRobots
                .Where(p => p.ProjectId == projectId)
                .Select(r =>
                   new ProjectRobot()
                   {
                       RobotId = r.MsRobot.RobotId,
                       Alias = r.MsRobot.Alias
                   }).AsNoTracking().ToListAsync().ConfigureAwait(false);
        }

        public async Task<List<ProjectMember>> GetProjectMember(Guid projectId)
        {
            return await
                (from up in Db.SysUserProject
                 join u in Db.SysUsers on up.UserId equals u.YunUserGuid

                 where up.ProjectId == projectId
                       //&& !up.IsDeleted
                       && !u.IsDeleted && u.Status.Equals(SysUser.EnumUserStatus.正常)
                 select new ProjectMember()
                 {
                     UserId = u.YunUserGuid,
                     UserName = u.Name
                 }).ToListAsync().ConfigureAwait(false);
        }

        public async Task<List<SelectItem>> GetUserProject()
        {
            return await (from p in Db.MsProjects
                          where GetUserProjects(tokenModel.Id).Result.Contains(p.ProjectId)
                            && !p.IsDeleted && p.Status == MsProject.ProjectStatus.启用
                          select new SelectItem(p.Name, p.ProjectId.ToString())
                ).AsNoTracking().ToListAsync().ConfigureAwait(false);
        }

        public async Task<List<ProjectHouseMap>> GetProjectHouseMap(Guid projectId)
        {
            var result = await (from p in Db.MsProjects
                                join h in Db.MsHouseMaps on p.ProjectId equals h.ProjectId
                                where !p.IsDeleted && p.Status == MsProject.ProjectStatus.启用 && p.ProjectId.Equals(projectId)
                                && h.Status == MsHouseMap.EnumHouseMapStatus.启用
                                orderby h.CreatedDate descending
                                select new ProjectHouseMap()
                                {
                                    HouseMapId = h.HouseMapId,
                                    ProjectId = p.ProjectId,
                                    ProjectName = p.Name,
                                    Name = h.Name,
                                    ImgSrc = ConfigHelper.GetValue<string>("FileServer") +
                               "/" + ConfigHelper.GetValue<string>("FileUploadFileMaster") + "/" + ConfigHelper.GetValue<string>("FileUploadFileSon") + "/" + h.Image_Base,
                                    MapType = (int)h.MapType,
                                    IsDeleted = h.IsDeleted,
                                    StandardMeasurePoints = new List<MeasurePoints>()
                                }).AsNoTracking().ToListAsync().ConfigureAwait(false);

            // 绑定站点信息
            foreach (var item in result)
            {
                var lis = await (from h in Db.MsHouseMapPoints
                                 join u in Db.MsPointTypes on new { id = h.MsPointTypeId, project = projectId } equals new { id = u.Id, project = u.ProjectGuid }
                                 where h.HouseMapId == item.HouseMapId
                                 select new MeasurePoints
                                 {
                                     PointId = h.PointId,
                                     pointIndex = h.PointIndex,
                                     x = h.x,
                                     y = h.y,
                                     offsetX = h.offsetX,
                                     offsetY = h.offsetY,
                                     Type = u.Type,
                                     TypeId = u.Id,
                                     TypeName = u.Name,
                                 }).AsNoTracking().OrderBy(x => x.pointIndex).ToListAsync().ConfigureAwait(false);
                item.StandardMeasurePoints = lis;

                if (item.StandardMeasurePoints == null || item.StandardMeasurePoints.Count == 0)
                {
                    continue;
                }
            }

            return result;
        }

        public async Task<ProjectHouseMap> GetProjectHouseMapModel(Guid projectId, Guid houseMapId)
        {
            var result = await (from p in Db.MsProjects
                                join h in Db.MsHouseMaps on p.ProjectId equals h.ProjectId
                                where !p.IsDeleted && p.Status == MsProject.ProjectStatus.启用 && p.ProjectId.Equals(projectId) && h.HouseMapId == houseMapId
                                && h.Status == MsHouseMap.EnumHouseMapStatus.启用
                                orderby h.CreatedDate descending
                                select new ProjectHouseMap()
                                {
                                    HouseMapId = h.HouseMapId,
                                    ProjectId = p.ProjectId,
                                    ProjectName = p.Name,
                                    Name = h.Name,
                                    ImgSrc = ConfigHelper.GetValue<string>("FileServer") +
                               "/" + ConfigHelper.GetValue<string>("FileUploadFileMaster") + "/" + ConfigHelper.GetValue<string>("FileUploadFileSon") + "/" + h.Image_Base,
                                    MapType = (int)h.MapType,
                                    IsDeleted = h.IsDeleted,
                                    StandardMeasurePoints = new List<MeasurePoints>()
                                }).AsNoTracking().ToListAsync().ConfigureAwait(false);

            // 绑定站点信息
            foreach (var item in result)
            {
                var lis = await (from h in Db.MsHouseMapPoints
                                 join u in Db.MsPointTypes on h.MsPointTypeId equals u.Id
                                 where h.HouseMapId == item.HouseMapId && u.ProjectGuid == projectId
                                 select new MeasurePoints
                                 {
                                     PointId = h.PointId,
                                     pointIndex = h.PointIndex,
                                     x = h.x,
                                     y = h.y,
                                     offsetX = h.offsetX,
                                     offsetY = h.offsetY,
                                     Type = u.Type,
                                     TypeId = u.Id,
                                     TypeName = u.Name,
                                     HouseTypeName = h.HouseTypeName,
                                     HouseTypeKey = h.HouseTypeKey
                                 }).AsNoTracking().OrderBy(x => x.pointIndex).ToListAsync().ConfigureAwait(false);
                item.StandardMeasurePoints = lis;

                if (item.StandardMeasurePoints == null || item.StandardMeasurePoints.Count == 0)
                {
                    continue;
                }

                // 绑定测量项和设计值
                foreach (var design in item.StandardMeasurePoints)
                {
                    var designValues = await (from x in Db.MsMeasureItems
                                              join j in Db.MsMeasureTemplates on new { HouseMapId = x.HouseMapId, PointId = x.Id } equals new { HouseMapId = j.HouseMapId, PointId = j.Id }
                                              where !j.IsDeleted && x.HouseMapId == item.HouseMapId && x.PointId == design.PointId
                                              select new MeasureItem
                                              {
                                                  HouseMapId = x.HouseMapId.ToString(),
                                                  PointId = x.PointId.ToString(),
                                                  Id = j.Id,
                                                  Code = j.Code,
                                                  Title = j.Title,
                                                  Type = (int)j.Type,                // 站点类型
                                                  Desc = string.Empty,
                                                  DesignValues = j.DesignValues.ToObject<List<DesignValue>>()
                                              }).AsNoTracking().ToListAsync().ConfigureAwait(false);
                    design.MeasureItems = designValues;
                }
            }

            return result.FirstOrDefault();
        }

        /// <summary>
        /// 获取匹配任务名称前缀的最大任务编号
        /// </summary>
        /// <param name="taskNamePrex"></param>
        /// <returns></returns>
        public async Task<int?> GetNextTaskNameNo(string taskNamePrex)
        {
            var list = await (from p in Db.MsTasks
                              where p.TaskName == taskNamePrex
                              select p.TaskNameNo).ToListAsync().ConfigureAwait(false);
            if (list == null || list.Count == 0)
            {
                return 0;
            }
            else
            {
                return list.Max() + 1;
            }
        }

        /// <summary>
        /// 获取匹配任务名称前缀的最大任务编号
        /// </summary>
        /// <returns></returns>
        public async Task<int?> GetNextTaskNameNo(Guid projectId, string build, string floor, string houseHolds, string taskProperty)
        {
            List<int?> list = null;
            if (!string.IsNullOrEmpty(houseHolds) && houseHolds != "-1")
            {
                list = await (from p in Db.MsTasks
                              where p.ProjectId == projectId && p.BuildingBlock == build && p.BuildingFloor == floor && p.HouseHolds == houseHolds
                              && p.TaskProperty == taskProperty
                              select p.TaskNameNo).ToListAsync().ConfigureAwait(false);
            }
            else
            {
                list = await (from p in Db.MsTasks
                              where p.ProjectId == projectId && p.BuildingBlock == build && p.BuildingFloor == floor && p.TaskProperty == taskProperty
                              select p.TaskNameNo).ToListAsync().ConfigureAwait(false);
            }

            if (list == null || list.Count == 0)
            {
                return 0;
            }
            else
            {
                return list.Max() + 1;
            }
        }

        /// <summary>
        /// 根据任务Id获取非跟踪级别对象
        /// </summary>
        /// <param name="taskId">任务Id</param>
        /// <returns></returns>
        public async Task<MsTask> GetMsTask(Guid taskId)
        {
            var model = await (from p in Db.MsTasks
                               where p.TaskId == taskId && !p.IsDeleted
                               select p).AsNoTracking().FirstOrDefaultAsync();
            return model;
        }

        /// <summary>
        /// 根据任务Id取任务站点
        /// </summary>
        /// <param name="taskId">任务Id</param>
        /// <returns></returns>
        public async Task<List<MeasurePoints>> GetTaskPoints(Guid taskId, Guid houseMapId)
        {
            var result = await (from p in Db.MsTasks
                                join h in Db.TaskPointss on p.TaskId equals h.TaskId
                                join u in Db.MsPointTypes on new { id = h.MsPointTypeId, projectId = p.ProjectId } equals new
                                {
                                    id = u.Id,
                                    projectId = u.ProjectGuid
                                }
                                where p.TaskId == taskId && !p.IsDeleted && !h.IsDeleted
                                orderby h.pintIndex ascending
                                select new MeasurePoints
                                {
                                    PointId = h.pointId,
                                    pointIndex = h.pintIndex,
                                    x = h.x,
                                    y = h.y,
                                    offsetX = h.offsetX,
                                    offsetY = h.offsetY,
                                    Type = u.Type,
                                    TypeId = u.Id,
                                    TypeName = u.Name,
                                    HouseTypeName = h.HouseTypeName,
                                    HouseTypeKey = h.HouseTypeKey,
                                }).AsNoTracking().OrderBy(x => x.pointIndex).ToListAsync().ConfigureAwait(false);

            // 绑定测量项和设计值
            foreach (var design in result)
            {
                var designValues = await (from x in Db.MSTaskPoint2ManualMeasurements
                                          join j in Db.MsTaskMeasureItemTemplates on x.MsTaskMeasureItemTemplateId equals j.MsTaskMeasureItemTemplateId
                                          where x.TaskId == taskId && x.PointId == design.PointId
                                          select new MeasureItem
                                          {
                                              HouseMapId = houseMapId.ToString(),
                                              PointId = x.PointId.ToString(),
                                              Id = j.Id,
                                              Code = j.Code,
                                              Title = j.Title,
                                              Type = (int)j.Type,                // 站点类型
                                              Desc = string.Empty,
                                              DesignValues = j.DesignValues.ToObject<List<DesignValue>>()
                                          }).AsNoTracking().ToListAsync().ConfigureAwait(false);
                design.MeasureItems = designValues;
            }
            return result;
        }

        /// <summary>
        /// 取同步的任务数据
        /// </summary>
        /// <param name="taskId"></param>
        /// <returns></returns>

        public async Task<MsTask> GetTaskData(Guid taskId)
        {
            DateTime beforeDt = System.DateTime.Now;
            var projectGuid = (from t in Db.MsTasks where t.TaskId == taskId select t.ProjectId).FirstOrDefault();
            var standards = DataStore.GetStandards(projectGuid);
            DateTime afterDT = System.DateTime.Now;
            TimeSpan ts = afterDT.Subtract(beforeDt);
            Logger.Info($"GetModel-GetStandards花费{ts.TotalSeconds}s.");
            beforeDt = System.DateTime.Now;

            var result = await (
                from t in Db.MsTasks
                join p in Db.MsProjects on t.ProjectId equals p.ProjectId
                join c in Db.SysUsers on t.CreatedBy equals c.YunUserGuid
                join u in Db.SysUsers on t.UserId equals u.YunUserGuid
                where t.TaskId == taskId && !t.IsDeleted
                select t
            ).AsNoTracking().SingleOrDefaultAsync().ConfigureAwait(false);
            var taskData = new SyncTaskData();
            if (result != null)
            {
                taskData = result.CopyTo<SyncTaskData>();
                taskData.ProjectStandardName = standards.Single(w => w.ProjectStandardId == result.ProjectStandardId).Stage;
                taskData.TaskTypeName = result.TaskType.ToString();
                taskData.ManualMeasurementInfo = string.Empty;

                #region 测量站点信息

                var points = await
                    (
                      from t in Db.MsTasks
                      join p in Db.TaskPointss on t.TaskId equals p.TaskId
                      //join q in Db.MsPointTypes on p.MsPointTypeId equals q.Id
                      where t.TaskId == taskId && !p.IsDeleted && !t.IsDeleted
                      select p
                    ).OrderBy(i => i.pintIndex).AsNoTracking().ToListAsync().ConfigureAwait(false);
                //taskData.Points = points;

                #endregion 测量站点信息

                #region 站点测量项

                List<string> robotMeasureItems = new List<string>();                      // 记录所有站点测量项（测量项并集）
                if (points != null && points.Count > 0)
                {
                    var taskMeasureItems = await (
                                   from a in Db.MSTaskPoint2ManualMeasurements
                                   where a.TaskId == taskId
                                   select a)
                                   .OrderBy(x => x.Code).AsNoTracking().ToListAsync().ConfigureAwait(false);

                    var pointTypes = await (from a in Db.MsPointTypes where a.ProjectGuid == projectGuid select a).AsNoTracking().ToListAsync().ConfigureAwait(false);
                    if (pointTypes == null || pointTypes.Count == 0)
                    {
                        throw new OperationException("站点类型表为空，请先维护基础数据");
                    }

                    List<MsTaskPointsEx> msTaskPoints = new List<MsTaskPointsEx>();
                    foreach (var point in points)
                    {
                        var msTaskPoint = point.CopyTo<MsTaskPointsEx>();
                        msTaskPoint.MeasureItems = taskMeasureItems.Where(p => p.PointId.ToString() == point.pointId.ToString()).ToList();
                        msTaskPoint.MsPointTypeName = pointTypes.Where(x => x.Id == point.MsPointTypeId).FirstOrDefault().Name;
                        msTaskPoints.Add(msTaskPoint);
                    }

                    taskData.Points = msTaskPoints;
                }

                #endregion 站点测量项

                #region 任务测量项模板

                var templates = await (
                    from t in Db.MsTasks
                    join p in Db.MsTaskMeasureItemTemplates on t.TaskId equals p.TaskId
                    where t.TaskId == taskId && !t.IsDeleted && p.Code != "r-kaijianjinshenpiancha"
                    select p).AsNoTracking().ToListAsync().ConfigureAwait(false);

                taskData.MeasureItemTemplates = templates;

                var useStandards = taskData.UseStandards.ToObject<UseStandard>();

                #endregion 任务测量项模板

                #region 任务标准库

                var taskStandards = await (
                    from t in Db.MsTasks
                    join p in Db.MsTaskStandards on t.TaskId equals p.TaskId
                    where t.TaskId == taskId && !t.IsDeleted
                    select p).AsNoTracking().ToListAsync().ConfigureAwait(false);

                taskData.Standards = taskStandards;
                string manualMeasurementInfo = string.Empty;
                StandardClass standardModelSig = result.UsestandardAllInfo.ToObject<StandardClass>();
                foreach (var item in useStandards.man)
                {
                    manualMeasurementInfo += $"{standardModelSig.Items.Where(x => x.Code == item).FirstOrDefault().Title} ";
                }
                if (manualMeasurementInfo.Length > 0)
                {
                    manualMeasurementInfo = manualMeasurementInfo.Substring(0, manualMeasurementInfo.Length - 1);
                }
                taskData.ManualMeasurementInfo = manualMeasurementInfo;

                #endregion 任务标准库

                #region 汇总人工测量数据

                var manualMeasureSummaryItems = await (
                    from t in Db.MsTasks
                    join p in Db.MsManualMeasureSummaryItems on t.TaskId equals p.TaskId
                    where t.TaskId == taskId && !t.IsDeleted
                    select p).AsNoTracking().ToListAsync().ConfigureAwait(false);

                if (manualMeasureSummaryItems == null || manualMeasureSummaryItems.Count == 0)
                {
                    List<MsManualMeasureSummaryItems> msManualMeasures = new List<MsManualMeasureSummaryItems>();
                    foreach (var item in useStandards.man)
                    {
                        var mm = standardModelSig.Items.Where(x => x.Code == item).FirstOrDefault();
                        if (mm == null)
                        {
                            throw new OperationException($"人工测量项【{item}】不存在于标准库");
                        }
                        msManualMeasures.Add(new MsManualMeasureSummaryItems()
                        {
                            ManualMeasureSummaryId = Guid.NewGuid(),
                            TaskId = taskId,
                            Title = mm.Title,
                            Code = mm.Code,
                            ActualMeasurementPoints = string.Empty,
                            ExplosionPoints = string.Empty,
                        });
                    }
                    taskData.ManualMeasureSummaryItems = msManualMeasures;
                }
                else
                {
                    taskData.ManualMeasureSummaryItems = manualMeasureSummaryItems;
                }

                #endregion 汇总人工测量数据

                #region 站点人工测量项

                var manualMeasureItems = await (
                    from t in Db.MsTasks
                    join p in Db.MSTaskPoint2ManualMeasurements on t.TaskId equals p.TaskId
                    where t.TaskId == taskId && !t.IsDeleted && p.Code != "r-kaijianjinshenpiancha"
                    select p).AsNoTracking().ToListAsync().ConfigureAwait(false);
                taskData.ManualMeasureItems = manualMeasureItems;

                #endregion 站点人工测量项
            }
            afterDT = System.DateTime.Now;
            ts = afterDT.Subtract(beforeDt);
            Logger.Info($"GetModel-分析result花费{ts.TotalSeconds}s.");

            return taskData;
        }

        /// <summary>
        /// 获取用户项目并设置缓存
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<List<Guid>> GetUserProjects(Guid userId)
        {
            return await cached.GetOrSet($"{StoreRule.RuleUserProjects}{userId}", async () =>
            {
                var list = await SysUserProjectRepository.WhereAsync(w => w.UserId == userId);
                return list.Select(w => w.ProjectId).ToList();
            }, GetCommonTimeSpan());
        }

        /// <summary>
        /// 删除项目缓存
        /// </summary>
        public void RemoveUserProjects()
        {
            cached.RemoveByRegex($"^{StoreRule.RuleUserProjects}");
        }

        public string GetHouseMapImage(Guid taskId)
        {
            var info = Db.CSMSTasks.Join(Db.MsHouseMaps, a => a.HouseMapId, b => b.HouseMapId, (a, b) => new { a.TaskId, b.Image_Base })
                                 .Where(x => x.TaskId == taskId).FirstOrDefault();

            return info?.Image_Base;
        }

        public async Task<MsTaskStatisticsInfo> GetTaskStatisticsInfoAsync(Guid taskId)
        {
            var info = await (from ts in Db.MsTasks
                              join pt in Db.MsProjects on ts.ProjectId equals pt.ProjectId
                              join cs in Db.CSMSTasks on ts.TaskId equals cs.TaskId
                              where ts.TaskId == taskId
                              select new MsTaskStatisticsInfo
                              {
                                  TaskId = ts.TaskId,
                                  UserId = ts.CreatedBy,
                                  HouseMapId = cs.HouseMapId,
                                  BuildingName = cs.BuildingName,
                                  FloorName = cs.FloorName,
                                  CompanyGuid = pt.CompanyGuid,
                                  DeviceGuid = cs.DeviceGuid,
                                  ProjectGuid = ts.ProjectId,
                                  ProjectName = pt.Name,
                                  ProjectNo = pt.ProjectNo,
                                  TaskType = ts.TaskType,
                                  ProjectStage = cs.ProjectStage,
                                  TaskProperty = ts.TaskProperty
                              }).AsNoTracking().FirstOrDefaultAsync();

            return info;
        }

        /// <summary>
        /// 获取分户汇总信息
        /// </summary>
        /// <param name="taskId">任务Id</param>
        /// <returns></returns>
        public async ValueTask<MsApartmentSunmaryInfoDto> GetApartmentSunmaryInfo(Guid taskId)
        {
            string sql = @$"SELECT a.""TaskId"",a.""TaskName"",a.""TaskType"",a.""BuildingBlock"" ""BuildingName"",a.""BuildingFloor"" ""FloorName"",
                            a.""ProjectId"",a.""SupportStandard"",a.""UsestandardAllInfo"",a.""Craft"",b.""Name"" ""ProjectName"",d.""ProjectStage"",
                            d.""ResultDataFilePath"",e.""Name"" ""UserName"",c.""completiontime"" ""FinishTime"",c.""measuresummaryinfo""
                            FROM ""MsTask"" a
                            inner join ""MsProject"" b on a.""ProjectId"" = b.""ProjectId""
                            inner join ""tasktable"" c on a.""TaskId"" = c.uuid
                            inner join ""CSMSTask"" d on a.""TaskId"" = d.""TaskId""
                            inner join ""SysUser"" e on a.""UserId"" = e.""YunUserGuid""
                            where a.""TaskId"" = '{taskId}' and a.""IsDeleted"" = false;";

            var info = await PgSqlHelper.QueryOneAsync<MsApartmentSunmaryInfoDto>(CommandType.Text, sql);

            return info;
        }

        public async ValueTask<bool> UpdateTaskStatusAsync(UpdateTaskStatusRequestDto dto)
        {
            var list = await Db.MsTasks.Where(p => dto.TaskIds.Contains(p.TaskId) && !p.IsDeleted).ToListAsync();
            list.ForEach(p =>
            {
                p.Status = dto.Status;
                p.LastUpdatedBy = tokenModel.Id;
                p.LastUpdatedDate = DateTime.Now;
            });

            var affrows = Db.SaveChanges();
            return affrows > 0;
        }

        public async ValueTask<TaskInfoBaseDto> GetBaseInfoAsync(Guid taskId)
        {
            var info = await (from ts in Db.MsTasks
                              join pt in Db.MsProjects on ts.ProjectId equals pt.ProjectId
                              where ts.TaskId == taskId
                              select new TaskInfoBaseDto
                              {
                                  TaskId = ts.TaskId,
                                  TaskName = ts.TaskName,
                                  ProjectStandardId = ts.ProjectStandardId,
                                  TaskProperty = ts.TaskProperty,
                                  TaskType = ts.TaskType,
                                  ProjectNo = pt.ProjectNo,
                              }).AsNoTracking().FirstOrDefaultAsync();

            return info;
        }
    }
}